package com.googlecode.volkien;

import java.util.ArrayList;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.provider.Settings;
import android.widget.Toast;

public class VolumeService extends Service {

	/*
	Thread mThread;
	VolumeWorker mVolumeWorker;

	class VolumeWorker implements Runnable {
		
		long mCounter;
		
		VolumeWorker() {
			mCounter = 0;
		}
		
		synchronized public long getCounter() {
			return mCounter;
		}

		public void run() {
			synchronized(this) {
				try {

					while (true) {
						wait(1000);
						mCounter++;
					}

				}
				catch (InterruptedException e) {

				}
			}
		}

	}*/
	
	boolean mEnabled = false;
	ArrayList<Messenger> mClients = new ArrayList<Messenger>();
	
	static final String ACTION_QUERY_STATUS = "query_status";
	static final String ACTION_ENABLE_VOLUME_CONTROL = "enable_volume_control";

	// message that ringer volume has changed
	static final int MSG_SERVICE_STATUS = 1;
	static final int MSG_RINGER_VOLUME_CHANGED = 2;
	static final int MSG_RINGER_MODE_CHANGED = 3;
	static final int MSG_DISABLE_VOLUME_CONTROL = 4;
	static final int MSG_REGISTER_CLIENT = 5;
	static final int MSG_UNREGISTER_CLIENT = 6;
	static final int MSG_QUERY_STATUS = 7;
	
	// a handler for incoming messages
	protected class IncomingHandler extends Handler {

		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			// handle change in ringer volume
			case MSG_RINGER_VOLUME_CHANGED:
				showToast("Ringer volume changed");
				break;
			case MSG_RINGER_MODE_CHANGED:
				showToast("Ringer mode changed");
				break;
			case MSG_REGISTER_CLIENT:
				mClients.add(msg.replyTo);
				break;
			case MSG_UNREGISTER_CLIENT:
				mClients.remove(msg.replyTo);
				break;
			case MSG_DISABLE_VOLUME_CONTROL:
				mEnabled = false;
				signalStatus();
				break;
			case MSG_QUERY_STATUS:
				signalStatus();
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}
	
	protected final Messenger mMessenger = new Messenger(new IncomingHandler());
	
	// an observer for ringer volume
	protected class SettingObserver extends ContentObserver {
		
		private int mWhat;

		public SettingObserver(int what) {
			super(null);
			mWhat = what;
		}

		@Override
		public void onChange(boolean selfChange) {
			super.onChange(selfChange);
			Message msg = Message.obtain(null, mWhat);
			try {
				mMessenger.send(msg);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	SettingObserver mRingerVolumeObserver;
	SettingObserver mRingerModeObserver;
	boolean mRingerVolumeObserverRegistered = false;
	
	void registerObservers() {
		if (!mRingerVolumeObserverRegistered) {
			
			// register a content observer to monitor changes in ringer volume
			mRingerVolumeObserver = new SettingObserver(MSG_RINGER_VOLUME_CHANGED);
			getContentResolver().registerContentObserver(Settings.System.getUriFor(Settings.System.VOLUME_RING), false, mRingerVolumeObserver);
			
			// register a content observer to monitor changes in ringer mode
			mRingerModeObserver = new SettingObserver(MSG_RINGER_MODE_CHANGED);
			getContentResolver().registerContentObserver(Settings.System.getUriFor(Settings.System.MODE_RINGER), false, mRingerModeObserver);
			
			mRingerVolumeObserverRegistered = true;
		}
	}
	
	public void signalStatus() {
		Message msg = Message.obtain(null, MSG_SERVICE_STATUS, null);
		if (mEnabled) {
			msg.arg1 = 1;
		}
		else {
			msg.arg1 = 0;
		}
		
		for (int i=mClients.size()-1; i>=0; i--) {
            try {
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                // The client is dead.  Remove it from the list;
                // we are going through the list from back to front
                // so this is safe to do inside the loop.
                mClients.remove(i);
            }
        }

	}

	void unregisterObservers() {
		if (mRingerVolumeObserverRegistered) {
			
			// unregister the observer for ringer volume
			getContentResolver().unregisterContentObserver(mRingerVolumeObserver);
			
			// unregister the observer for ringer mode
			getContentResolver().unregisterContentObserver(mRingerModeObserver);
			
			mRingerVolumeObserverRegistered = false;
		}
	}
	
	PendingIntent mWakeupIntent;
	boolean mWakeupScheduled = false;
	
	void scheduleWakeup() {
		if (!mWakeupScheduled) {
			Intent intent = new Intent(this, VolumeService.class);
			mWakeupIntent = PendingIntent.getService(this, 0, intent, 0);
			AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
			alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), AlarmManager.INTERVAL_HALF_HOUR, mWakeupIntent);
			mWakeupScheduled = true;
		}
	}
	
	void cancelWakeup() {
		if (mWakeupScheduled) {
			AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
			alarm.cancel(mWakeupIntent);
			mWakeupScheduled = false;
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		// return the binder to our messenger for anyone wanting to bind to our service
		return mMessenger.getBinder();
	}

	@Override
	public void onCreate() {
		//Toast.makeText(this, "onCreate", Toast.LENGTH_SHORT).show();
		//mThread = new Thread(mVolumeWorker = new VolumeWorker());
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		//Toast.makeText(this, "onStartCommand", Toast.LENGTH_SHORT).show();
		//mThread.start();
		//registerObservers();
		//scheduleWakeup();
		
		int result = 0;
		
		// return START_STICKY to signal that service should stay alive even with no clients bound
		if (intent.getAction().equals(ACTION_ENABLE_VOLUME_CONTROL)) {
			mEnabled = true;
			signalStatus();
			result = START_STICKY;
		}
		else {
			result = START_NOT_STICKY;
		}
		return result;
	}

	@Override
	public void onDestroy() {
		//Toast.makeText(this, "onDestroy" + mVolumeWorker.getCounter(), Toast.LENGTH_SHORT).show();
		//mThread.interrupt();
		
		//unregisterObservers();
		//cancelWakeup();
		
	}

	private void showToast(String msg) {
		Toast.makeText(VolumeService.this, msg, Toast.LENGTH_SHORT).show();
	}
}
